package com.jprocms.module.cms.service.content;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.page.PageMethod;
import com.jpro.framework.common.pojo.PageResult;
import com.jpro.framework.common.util.collection.CollectionUtils;
import com.jprocms.module.cms.controller.admin.content.relatevo.ContentRelateBatchCreateReqVO;
import com.jprocms.module.cms.controller.admin.content.relatevo.ContentRelateReqVO;
import com.jprocms.module.cms.controller.admin.content.relatevo.ContentRelateSortVO;
import com.jprocms.module.cms.convert.PageConverter;
import com.jprocms.module.cms.dal.dataobject.content.ContentDO;
import com.jprocms.module.cms.dal.dataobject.content.ContentRelateDO;
import com.jprocms.module.cms.dal.mysql.content.ContentMapper;
import com.jprocms.module.cms.dal.mysql.content.ContentRelateMapper;
import com.jprocms.module.cms.enums.EnumContentStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static com.jpro.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.jprocms.module.cms.constant.CmsSysConstants.DEF_SORT;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.CONTENT_NOT_EXISTS;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.CONTENT_RELATE_NOT_EXISTS;

/**
 * 相关内容 Service 实现类
 *
 * @author jprocms
 */
@Service
@Validated
public class ContentRelateServiceImpl implements ContentRelateService {

    @Resource
    private ContentRelateMapper contentRelateMapper;
    @Resource
    private PageConverter pageConverter;

    @Resource
    private ContentMapper contentMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createContentRelate(ContentRelateBatchCreateReqVO createReqVO) {
        List<Long> relateIds = createReqVO.getRelateIds();
        List<ContentRelateDO> contentRelateDOS = contentRelateMapper.selectList(ContentRelateDO::getContentId, createReqVO.getContentId());
        List<Long> existRelateIds = CollectionUtils.convertList(contentRelateDOS, ContentRelateDO::getRelateId);
        List<Long> toSaves = CollUtil.subtractToList(relateIds, existRelateIds);
        for (Long relateId : toSaves) {
            // 插入
            ContentRelateDO contentRelateDO = new ContentRelateDO(createReqVO.getContentId(), relateId, DEF_SORT);
            contentRelateMapper.insert(contentRelateDO);
        }
    }


    @Override
    public void deleteContentRelate(Long id) {
        // 校验存在
        validateContentRelateExists(id);
        // 删除
        contentRelateMapper.deleteById(id);
    }

    @Override
    public void sortContentRelate(ContentRelateSortVO sortVO) {
        //先查询当前id关联的内容有那些相关内容，然后进行分批修改
        ContentRelateDO contentRelate = getContentRelate(sortVO.getId());
        if (contentRelate == null) {
            throw exception(CONTENT_RELATE_NOT_EXISTS);
        }
        ContentDO relateContent = contentRelate.getRelateContent();
        if (relateContent == null) {
            throw exception(CONTENT_NOT_EXISTS);
        }
        ContentRelateReqVO contentRelateReqVO = new ContentRelateReqVO();
        contentRelateReqVO.setContentId(contentRelate.getContentId());
        List<ContentRelateDO> relateDOS = contentRelateMapper.selectList(contentRelateReqVO);
        int relateCount = relateDOS.size();
        //先按顺序倒序重置一次
        for (int i = 0; i < relateDOS.size(); i++) {
            ContentRelateDO contentRelateDO = relateDOS.get(i);
            contentRelateDO.setSort(relateCount - i);
        }
        ContentRelateDO contentRelateDO = relateDOS.get(sortVO.getCurrIndex());
        contentRelateDO.setSort(contentRelateDO.getSort() + sortVO.getIncre());
        if (sortVO.getIncre() < 0) {
            if (sortVO.getCurrIndex() != relateCount - 1) {
                //下移 下个元素+1
                ContentRelateDO nextDo = relateDOS.get(sortVO.getCurrIndex() + 1);
                nextDo.setSort(contentRelateDO.getSort() - sortVO.getIncre());
            }
        } else {
            //上移
            if (sortVO.getCurrIndex() != 0) {
                //上移 上个元素-1
                ContentRelateDO preDo = relateDOS.get(sortVO.getCurrIndex() - 1);
                preDo.setSort(contentRelateDO.getSort() - sortVO.getIncre());
            }
        }
        contentRelateMapper.updateBatch(relateDOS, relateCount);
    }

    private void validateContentRelateExists(Long id) {
        if (contentRelateMapper.selectById(id) == null) {
            throw exception(CONTENT_RELATE_NOT_EXISTS);
        }
    }

    @Override
    public ContentRelateDO getContentRelate(Long id) {
        return contentRelateMapper.selectById(id);
    }

    @Override
    public List<ContentRelateDO> getContentRelateList(Collection<Long> ids) {
        return contentRelateMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<ContentRelateDO> getContentRelateList(ContentRelateReqVO reqVO) {
        return pageConverter.page(contentRelateMapper.selectPage(reqVO, new Page<>(reqVO.getPageNo(), reqVO.getPageSize())));
    }

    @Override
    public List<ContentDO> getContentRelateListFront(ContentRelateReqVO reqVO) {
        List<ContentRelateDO> relateDOS = PageMethod.offsetPage(0, reqVO.getCount(), false).doSelectPage(() -> contentRelateMapper.selectList(reqVO));
        if (CollectionUtils.isAnyEmpty(relateDOS)) {
            return Collections.emptyList();
        }
        return contentMapper.selectByContentIds(CollectionUtils.convertList(relateDOS, ContentRelateDO::getRelateId), EnumContentStatus.PUBLISHED.getStatus());
    }
}
